package com.fmi.timedealer.datamanager;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import android.database.SQLException;

import com.fmi.timedealer.Category;
import com.fmi.timedealer.ActivityItem;
import com.fmi.timedealer.achievement.Achievement;
import com.fmi.timedealer.achievement.AchievementLevel;
import com.fmi.timedealer.achievement.AchievementLevelItem;
import com.fmi.timedealer.moodtracking.TrackedMood;
import com.fmi.timedealer.plan.Plan;
import com.fmi.timedealer.plan.PlannedActivity;
import com.fmi.timedealer.reporting.model.ActivitiesPerCategoryReportItem;
import com.fmi.timedealer.reporting.model.CategoriesReportItem;
import com.fmi.timedealer.reporting.model.CustomReportItem;
import com.fmi.timedealer.reporting.model.MoodReportItem;
import com.fmi.timedealer.track.TrackLog;

public interface IDataManager {
	
	/**
	 * Persists the given ActivityItem to the DB
	 * @param item the ActivityItem to be persisted
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean recordActivityItem(ActivityItem activityItem) throws SQLException;
	
	/**
	 * Updates an ActivityItem
	 * @param activityItem the ActivityItem to be updated
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean updateActivityItem(ActivityItem activityItem) throws SQLException;
	
	/**
	 * Deletes a ActivityItem from the DB
	 * @param activityItem the ActivityItem to be deleted
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean deleteActivityItem(ActivityItem activityItem) throws SQLException;
	
	/**
	 * Retrieves all category names from the database
	 * @return array of String objects with the category names
	 */
	public String[] getCategoriesNames();
	
	/**
	 * Persists a Plan in the database
	 * @param plan the Plan object that will be persisted
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean insertPlan(Plan plan) throws SQLException;
	
	/**
	 * Return all Plans
	 * @return ArrayList of Plan objects
	 * @throws SQLException
	 */
	public ArrayList<Plan> getPlans() throws SQLException;

	/**
	 * Updates the given Plan
	 * @param plan the updated Plan
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean updatePlan(Plan plan) throws SQLException;
	
	/**
	 * Deletes the given Plan
	 * @param plan the Plan to be deleted
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean deletePlan(Plan plan) throws SQLException;
	
	/**
	 * Checks whether the given ActivityItem is currently running
	 * @param activity
	 * @return true if the ActivityItem is running, otherwise - false
	 */
	public boolean isActivityRunning(ActivityItem activity);
	
	/**
	 * Tracks time for the given ActivityItem
	 * @param activity the ActivityItem
	 * @param startDate start date of the ActivityItem
	 * @param endDate end date of the ActivityItem; null if it is still running
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean trackTime(ActivityItem activity, Date startDate, Date endDate);
	
	/**
	 * Returns all activities based on their running status
	 * @param onlyActive true for running activities, false for past events
	 * @return ArrayList of TrackLog objects based on the given running status
	 * @throws SQLException
	 */
	public ArrayList<TrackLog> getActivities(boolean onlyActive) throws SQLException;
	
	/**
	 * Retrieves all ActivityItem objects based on the given activity IDs
	 * @param activityIds the activity IDs
	 * @return HashMap of activity ID to ActivityItem object
	 */
	public HashMap<Long, ActivityItem> getActivitiesByIds(long[] activityIds);
	
	/**
	 * Stops tracking for the given ActivityItem
	 * @param activity the running ActivityItem that should be stopped
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean stopTracking(ActivityItem activity);
	
	/**
	 * Retrieves all CustomReportItem objects based on the given category, start and end dates
	 * @param category the category criteria
	 * @param start the start date
	 * @param end the end date
	 * @return List of CustomReportItem
	 */
	public List<CustomReportItem> getReport(String category, Date start, Date end);
	
	/**
	 * Retrieves all planned activities for the given plan
	 * @param planId the ID of the plan
	 * @return ArrayList of PlannedActivity objects for the given plan ID
	 */
	public ArrayList<PlannedActivity> getPlannedActivities(int planId);
	
	/**
	 * Persists a planned activity in the database
	 * @param plannedActivity the planned activity to be persisted
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean insertPlannedActivity(PlannedActivity plannedActivity) throws SQLException;
	
	/**
	 * Updates the given planned activity
	 * @param plannedActivity the planned activity to be updated
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean updatePlannedActivity(PlannedActivity plannedActivity) throws SQLException;
	
	/**
	 * Deletes the given planned activity
	 * @param plannedActivity the planned activity to be deleted
	 * @return true if the operation is successful, otherwise - false
	 * @throws SQLException
	 */
	public boolean deletePlannedActivity(PlannedActivity plannedActivity) throws SQLException;
	
	/**
	 * Retrieves all activity items from the database
	 * @return all ActivityItem objects
	 * @throws SQLException
	 */
	public ArrayList<ActivityItem> getAllActivities() throws SQLException;
	
	/**
	 * Retrieves all categories from the database
	 * @return all Category objects
	 */
	public List<Category> getAllCategories();

	/**
	 * Retrieves the activity items for the given category
	 * @param category the category criteria
	 * @return List containing all ActivityItem objects for the category
	 */
	public List<ActivityItem> getActivitiesForCategory(String category);
	
	/**
	 * Persists a category in the database
	 * @param category the Category to be persisted
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean insertCategory(Category category);

	/**
	 * Deletes a category from the database
	 * @param category the Category to be deleted
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean deleteCategory(Category category);

	/**
	 * Updates a category in the database
	 * @param category the Category to be updated
	 * @param oldCategoryName the old category name
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean updateCategory(Category category, String oldCategoryName);
	
	/**
	 * Retrieves the time spent in minutes for the given planned activity
	 * @param activity the PlannedActivity
	 * @return time spent in minutes
	 */
	public int getTimeSpentForPlannedActivity(PlannedActivity activity);
	
	/**
	 * Persists an achievement in the database
	 * @param achievement the Achievement to be persisted
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean insertAchievement(Achievement achievement);
	
	/**
	 * Retrieves all achievements from the database
	 * @return ArrayList of all Achievement objects
	 */
	public ArrayList<Achievement> getAchievements();

	/**
	 * Updates the given achievement
	 * @param achievement the Achievement to be updated
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean updateAchievement(Achievement achievement);
	
	/**
	 * Deletes the given achievement
	 * @param achievement the Achievement to be deleted
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean deleteAchievement(Achievement achievement);
	
	/**
	 * Retrieves all achievement levels for the given achievement
	 * @param achievementId the ID of the Achievement
	 * @return ArrayList of all AchievementLevel objects for the achievement
	 */
	public ArrayList<AchievementLevel> getLevelsForId(int achievementId);
	
	/**
	 * Updates the given achievement level
	 * @param level the AchievementLevel to be updated
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean updateLevel(AchievementLevel level);
	
	/**
	 * Deletes the given achievement level
	 * @param level the AchievementLevel to be deleted
	 * @param achievementId the ID of the parent Achievement containing the AchievementLevel
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean deleteLevel(AchievementLevel level, int achievementId);
	
	/**
	 * Persists an achievement level in the database
	 * @param level the AchievementLevel to be persisted
	 * @param achievementId the ID of the parent Achievement containing the AchievementLevel
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean insertLevel(AchievementLevel level, int achievementId);
	
	/**
	 * Retrieves all level items for the given level
	 * @param levelId the ID of the Level
	 * @return ArrayList of all AchievementLevelItem objects for the given Level
	 */
	public ArrayList<AchievementLevelItem> getLevelItemsForId(int levelId);
	
	/**
	 * Retrieves the achievement IDs for the given levels
	 * @param levels ArrayList of AchievementLevel objects
	 * @return ArrayList of the achievement IDs
	 */
	public ArrayList<Integer> getAchievementIdsForLevels(ArrayList<AchievementLevel> levels);
	
	/**
	 * Retrieves all levels for the given level items
	 * @param items List of AchievementLevelItems
	 * @return ArrayList of AchievementLevel objects for the given AchievementLevelItems
	 */
	public ArrayList<AchievementLevel> getLevelsByLevelItems(List<AchievementLevelItem> items);
	
	/**
	 * Updates the given achievement level item
	 * @param levelItem the AchievementLevelItem to be updated
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean updateLevelItem(AchievementLevelItem levelItem);
	
	/**
	 * Deletes the given achievement level item
	 * @param levelItem the AchievementLevelItem to be deleted
	 * @param levelId the ID of the parent Level containing the level item
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean deleteLevelItem(AchievementLevelItem levelItem, int levelId);
	
	/**
	 * Persists an achievement level item for the given level
	 * @param levelItem the AchievementLevelItem to be persisted
	 * @param levelId the ID of the AchievementLevel
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean insertLevelItem(AchievementLevelItem levelItem, int levelId);
	
	/**
	 * Updates the remaining time on all not completed level items
	 * @return ArrayLIst of the updated AchievementLevelItem objects
	 */
	public ArrayList<AchievementLevelItem> updateNotCompletedLevelItems();
	
	/**
	 * Tracks the mood
	 * @param trackedMood the mood
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean trackMood(TrackedMood trackedMood);
	
	/**
	 * Retrieves the time in minutes spent for the given activity
	 * @param activityId
	 * @return
	 */
	public int getTimeSpentForActivity(int activityId);
	
	/**
	 * Updates the mood
	 * @param mood the mood
	 * @return true if the operation is successful, otherwise - false
	 */
	public boolean updateMood(TrackedMood mood);
	
	/**
	 * Returns the current mood
	 * @return the code of the current mood
	 */
	public int getCurrentMoodCode();
	
	/**
	 * Retrieves all report items for the activities report
	 * @param category the chosen category
	 * @return List of ActivitiesPerCategoryReportItem matching the chosen criteria
	 */
	public List<ActivitiesPerCategoryReportItem> getActivitiesPieChart(String category);
	
	/**
	 * Updates all track rows
	 */
	public void updateTrackRows();
	
	/**
	 * Retrieves all report items for the categories report
	 * @param period the chosen period
	 * @return List of CategoriesReportItem objects matching the chosen criteria
	 */
	public List<CategoriesReportItem> getCategoriesPieChart(String period);

	/**
	 * Retrieves the mood log
	 * @return List of all MoodReportItem objects
	 */
	public List<MoodReportItem> getMoodLog();
	
	/**
	 * Retrieves all track logs
	 * @return List of all TrackLog objects
	 */
	public List<TrackLog> getAllTracks();
}